{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# LoRA\n",
    "Low-Rank Adaptation, 低秩适配。\n",
    "\n",
    "通过训练少量参数，来微调模型。\n"
   ],
   "id": "76746a9b4871e2a8"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from modelscope import AutoModelForCausalLM\n",
    "from modelscope import AutoTokenizer\n",
    "\n",
    "model_name = \"Qwen/Qwen3-0.6B\"\n",
    "model = AutoModelForCausalLM.from_pretrained(model_name)\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name)"
   ],
   "id": "dcec0dcad5bc3b5a",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T10:52:57.049488Z",
     "start_time": "2025-07-17T10:52:57.046963Z"
    }
   },
   "cell_type": "code",
   "source": [
    "prompt = \"你是谁\"\n",
    "messages = [\n",
    "    {\"role\": \"user\", \"content\": prompt}\n",
    "]\n",
    "text = tokenizer.apply_chat_template(\n",
    "    messages,\n",
    "    tokenize=False,\n",
    "    add_generation_prompt=True,\n",
    "    enable_thinking=False,  # 关闭了思考模式\n",
    ")\n",
    "print(text)"
   ],
   "id": "31f54175c7dbce16",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<|im_start|>user\n",
      "你是谁<|im_end|>\n",
      "<|im_start|>assistant\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "\n"
     ]
    }
   ],
   "execution_count": 5
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T10:53:59.953735Z",
     "start_time": "2025-07-17T10:53:57.419169Z"
    }
   },
   "cell_type": "code",
   "source": [
    "model_inputs = tokenizer([text], return_tensors=\"pt\")\n",
    "generated_ids = model.generate(**model_inputs, max_new_tokens=32768)\n",
    "content = tokenizer.decode(generated_ids[0])\n",
    "print(content)"
   ],
   "id": "3e9d664edaffc1f9",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<|im_start|>user\n",
      "你是谁<|im_end|>\n",
      "<|im_start|>assistant\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "我是一个AI助手，我不会直接回答“你是谁”，但可以提供帮助。你可以告诉我你需要什么帮助，我会尽力为你服务！<|im_end|>\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T10:59:10.192060Z",
     "start_time": "2025-07-17T10:59:10.188952Z"
    }
   },
   "cell_type": "code",
   "source": [
    "data = [\n",
    "    {\"Q\": \"你是谁\", \"A\": \"我是大都督周瑜的AI助手\"}\n",
    "]"
   ],
   "id": "b723256f3b44a694",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "# prompt = \"问题:你是谁\\n答案:我是大都督周瑜的AI助手\"",
   "id": "efa7c1f3ddc7ccde"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "<|im_start|>user\n",
    "{你是谁}<|im_end|>\n",
    "<|im_start|>assistant\n",
    "<think>\n",
    "\n",
    "</think>\n",
    "{我是大都督周瑜的AI助手}<|im_end|>"
   ],
   "id": "92c591d1861ea3b3"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T10:59:39.795979Z",
     "start_time": "2025-07-17T10:59:18.059818Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torch.utils.data import Dataset, DataLoader\n",
    "\n",
    "lora_prompt_template = \"\"\"\n",
    "<|im_start|>user\n",
    "{question}<|im_end|>\n",
    "<|im_start|>assistant\n",
    "<think>\n",
    "\n",
    "</think>\n",
    "{answer}\n",
    "<|im_end|>\"\"\"\n",
    "\n",
    "\n",
    "class ZhouyuDataset(Dataset):\n",
    "    def __init__(self, data, max_length=128):\n",
    "        self.encodings = []\n",
    "        for qa in data:\n",
    "            text = lora_prompt_template.format(question=qa[\"Q\"], answer=qa[\"A\"])\n",
    "            encoded = tokenizer(\n",
    "                text,\n",
    "                max_length=max_length,\n",
    "                padding='max_length',\n",
    "                truncation=True,\n",
    "                return_tensors='pt'\n",
    "            )\n",
    "            input_ids = encoded['input_ids'].squeeze()\n",
    "            self.encodings.append(input_ids)\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.encodings)\n",
    "\n",
    "    def __getitem__(self, idx):\n",
    "        return self.encodings[idx]\n",
    "\n",
    "\n",
    "dataset = ZhouyuDataset(data)\n",
    "data_loader = DataLoader(dataset, batch_size=1, shuffle=True)\n",
    "for batch in data_loader:\n",
    "    print(batch)\n",
    "    break"
   ],
   "id": "dad97ba67b6cd2a4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[   198, 151644,    872,    198, 105043, 100165, 151645,    198, 151644,\n",
      "          77091,    198, 151667,    271, 151668,    198, 104198,  26288,  71268,\n",
      "          99625,  40542, 103487,   9370,  15469, 110498,    198, 151645, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643, 151643,\n",
      "         151643, 151643]])\n"
     ]
    }
   ],
   "execution_count": 10
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T10:59:51.343649Z",
     "start_time": "2025-07-17T10:59:51.336160Z"
    }
   },
   "cell_type": "code",
   "source": "tokenizer.decode(151645), tokenizer.decode(151643)",
   "id": "ff93392c75a7c724",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('<|im_end|>', '<|endoftext|>')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:00:00.452703Z",
     "start_time": "2025-07-17T11:00:00.447894Z"
    }
   },
   "cell_type": "code",
   "source": "tokenizer.special_tokens_map",
   "id": "2c78e50c9b3ea4ca",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'eos_token': '<|im_end|>',\n",
       " 'pad_token': '<|endoftext|>',\n",
       " 'additional_special_tokens': ['<|im_start|>',\n",
       "  '<|im_end|>',\n",
       "  '<|object_ref_start|>',\n",
       "  '<|object_ref_end|>',\n",
       "  '<|box_start|>',\n",
       "  '<|box_end|>',\n",
       "  '<|quad_start|>',\n",
       "  '<|quad_end|>',\n",
       "  '<|vision_start|>',\n",
       "  '<|vision_end|>',\n",
       "  '<|vision_pad|>',\n",
       "  '<|image_pad|>',\n",
       "  '<|video_pad|>']}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 12
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:01:00.008653Z",
     "start_time": "2025-07-17T11:00:59.076986Z"
    }
   },
   "cell_type": "code",
   "source": "!pip install peft",
   "id": "43ab3f403bda5a7f",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n",
      "To disable this warning, you can either:\n",
      "\t- Avoid using `tokenizers` before the fork if possible\n",
      "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: peft in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (0.16.0)\r\n",
      "Requirement already satisfied: numpy>=1.17 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (2.2.6)\r\n",
      "Requirement already satisfied: packaging>=20.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (25.0)\r\n",
      "Requirement already satisfied: psutil in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (7.0.0)\r\n",
      "Requirement already satisfied: pyyaml in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (6.0.2)\r\n",
      "Requirement already satisfied: torch>=1.13.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (2.7.1)\r\n",
      "Requirement already satisfied: transformers in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (4.52.4)\r\n",
      "Requirement already satisfied: tqdm in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (4.67.1)\r\n",
      "Requirement already satisfied: accelerate>=0.21.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (1.9.0)\r\n",
      "Requirement already satisfied: safetensors in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (0.5.3)\r\n",
      "Requirement already satisfied: huggingface_hub>=0.25.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from peft) (0.33.0)\r\n",
      "Requirement already satisfied: filelock in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from huggingface_hub>=0.25.0->peft) (3.18.0)\r\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from huggingface_hub>=0.25.0->peft) (2024.9.0)\r\n",
      "Requirement already satisfied: requests in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from huggingface_hub>=0.25.0->peft) (2.32.4)\r\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from huggingface_hub>=0.25.0->peft) (4.14.0)\r\n",
      "Requirement already satisfied: hf-xet<2.0.0,>=1.1.2 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from huggingface_hub>=0.25.0->peft) (1.1.5)\r\n",
      "Requirement already satisfied: sympy>=1.13.3 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from torch>=1.13.0->peft) (1.14.0)\r\n",
      "Requirement already satisfied: networkx in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from torch>=1.13.0->peft) (3.4.2)\r\n",
      "Requirement already satisfied: jinja2 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from torch>=1.13.0->peft) (3.1.6)\r\n",
      "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from sympy>=1.13.3->torch>=1.13.0->peft) (1.3.0)\r\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from jinja2->torch>=1.13.0->peft) (3.0.2)\r\n",
      "Requirement already satisfied: charset_normalizer<4,>=2 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from requests->huggingface_hub>=0.25.0->peft) (3.4.2)\r\n",
      "Requirement already satisfied: idna<4,>=2.5 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from requests->huggingface_hub>=0.25.0->peft) (3.10)\r\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from requests->huggingface_hub>=0.25.0->peft) (2.4.0)\r\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from requests->huggingface_hub>=0.25.0->peft) (2025.4.26)\r\n",
      "Requirement already satisfied: regex!=2019.12.17 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from transformers->peft) (2024.11.6)\r\n",
      "Requirement already satisfied: tokenizers<0.22,>=0.21 in /Users/dadudu/miniconda3/envs/mini-gpt/lib/python3.10/site-packages (from transformers->peft) (0.21.2)\r\n"
     ]
    }
   ],
   "execution_count": 13
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:01:07.318685Z",
     "start_time": "2025-07-17T11:01:07.312948Z"
    }
   },
   "cell_type": "code",
   "source": "print(model)",
   "id": "29c5325408d717ba",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Qwen3ForCausalLM(\n",
      "  (model): Qwen3Model(\n",
      "    (embed_tokens): Embedding(151936, 1024)\n",
      "    (layers): ModuleList(\n",
      "      (0-27): 28 x Qwen3DecoderLayer(\n",
      "        (self_attn): Qwen3Attention(\n",
      "          (q_proj): Linear(in_features=1024, out_features=2048, bias=False)\n",
      "          (k_proj): Linear(in_features=1024, out_features=1024, bias=False)\n",
      "          (v_proj): Linear(in_features=1024, out_features=1024, bias=False)\n",
      "          (o_proj): Linear(in_features=2048, out_features=1024, bias=False)\n",
      "          (q_norm): Qwen3RMSNorm((128,), eps=1e-06)\n",
      "          (k_norm): Qwen3RMSNorm((128,), eps=1e-06)\n",
      "        )\n",
      "        (mlp): Qwen3MLP(\n",
      "          (gate_proj): Linear(in_features=1024, out_features=3072, bias=False)\n",
      "          (up_proj): Linear(in_features=1024, out_features=3072, bias=False)\n",
      "          (down_proj): Linear(in_features=3072, out_features=1024, bias=False)\n",
      "          (act_fn): SiLU()\n",
      "        )\n",
      "        (input_layernorm): Qwen3RMSNorm((1024,), eps=1e-06)\n",
      "        (post_attention_layernorm): Qwen3RMSNorm((1024,), eps=1e-06)\n",
      "      )\n",
      "    )\n",
      "    (norm): Qwen3RMSNorm((1024,), eps=1e-06)\n",
      "    (rotary_emb): Qwen3RotaryEmbedding()\n",
      "  )\n",
      "  (lm_head): Linear(in_features=1024, out_features=151936, bias=False)\n",
      ")\n"
     ]
    }
   ],
   "execution_count": 14
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:01:34.134545Z",
     "start_time": "2025-07-17T11:01:34.129618Z"
    }
   },
   "cell_type": "code",
   "source": "print(f'参数量：{sum(p.numel() for p in model.parameters())}')",
   "id": "36892592dda717fb",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "参数量：596049920\n"
     ]
    }
   ],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:07:09.309327Z",
     "start_time": "2025-07-17T11:07:09.285496Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from peft import LoraConfig, get_peft_model, TaskType\n",
    "\n",
    "lora_config = LoraConfig(\n",
    "    task_type=TaskType.CAUSAL_LM,\n",
    "    r=2,\n",
    "    target_modules=[\"q_proj\", \"k_proj\", \"v_proj\"]\n",
    ")\n",
    "\n",
    "# 应用LoRA\n",
    "lora_model = get_peft_model(model, lora_config)\n",
    "lora_model.print_trainable_parameters()  # 查看可训练参数"
   ],
   "id": "f574c3617ff84d25",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "trainable params: 401,408 || all params: 596,451,328 || trainable%: 0.0673\n"
     ]
    }
   ],
   "execution_count": 51
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:08:33.935360Z",
     "start_time": "2025-07-17T11:08:33.929236Z"
    }
   },
   "cell_type": "code",
   "source": "596049920+401408",
   "id": "bcb67e398e13761f",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "596451328"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 54
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:07:23.746077Z",
     "start_time": "2025-07-17T11:07:23.739565Z"
    }
   },
   "cell_type": "code",
   "source": "print(f'参数量：{sum(p.numel() for p in model.parameters())}')",
   "id": "d946c533e118431c",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "参数量：596451328\n"
     ]
    }
   ],
   "execution_count": 52
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:07:52.308264Z",
     "start_time": "2025-07-17T11:07:52.302004Z"
    }
   },
   "cell_type": "code",
   "source": "print(model)",
   "id": "228947e547f95559",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Qwen3ForCausalLM(\n",
      "  (model): Qwen3Model(\n",
      "    (embed_tokens): Embedding(151936, 1024)\n",
      "    (layers): ModuleList(\n",
      "      (0-27): 28 x Qwen3DecoderLayer(\n",
      "        (self_attn): Qwen3Attention(\n",
      "          (q_proj): lora.Linear(\n",
      "            (base_layer): Linear(in_features=1024, out_features=2048, bias=False)\n",
      "            (lora_dropout): ModuleDict(\n",
      "              (default): Identity()\n",
      "            )\n",
      "            (lora_A): ModuleDict(\n",
      "              (default): Linear(in_features=1024, out_features=2, bias=False)\n",
      "            )\n",
      "            (lora_B): ModuleDict(\n",
      "              (default): Linear(in_features=2, out_features=2048, bias=False)\n",
      "            )\n",
      "            (lora_embedding_A): ParameterDict()\n",
      "            (lora_embedding_B): ParameterDict()\n",
      "            (lora_magnitude_vector): ModuleDict()\n",
      "          )\n",
      "          (k_proj): lora.Linear(\n",
      "            (base_layer): Linear(in_features=1024, out_features=1024, bias=False)\n",
      "            (lora_dropout): ModuleDict(\n",
      "              (default): Identity()\n",
      "            )\n",
      "            (lora_A): ModuleDict(\n",
      "              (default): Linear(in_features=1024, out_features=2, bias=False)\n",
      "            )\n",
      "            (lora_B): ModuleDict(\n",
      "              (default): Linear(in_features=2, out_features=1024, bias=False)\n",
      "            )\n",
      "            (lora_embedding_A): ParameterDict()\n",
      "            (lora_embedding_B): ParameterDict()\n",
      "            (lora_magnitude_vector): ModuleDict()\n",
      "          )\n",
      "          (v_proj): lora.Linear(\n",
      "            (base_layer): Linear(in_features=1024, out_features=1024, bias=False)\n",
      "            (lora_dropout): ModuleDict(\n",
      "              (default): Identity()\n",
      "            )\n",
      "            (lora_A): ModuleDict(\n",
      "              (default): Linear(in_features=1024, out_features=2, bias=False)\n",
      "            )\n",
      "            (lora_B): ModuleDict(\n",
      "              (default): Linear(in_features=2, out_features=1024, bias=False)\n",
      "            )\n",
      "            (lora_embedding_A): ParameterDict()\n",
      "            (lora_embedding_B): ParameterDict()\n",
      "            (lora_magnitude_vector): ModuleDict()\n",
      "          )\n",
      "          (o_proj): Linear(in_features=2048, out_features=1024, bias=False)\n",
      "          (q_norm): Qwen3RMSNorm((128,), eps=1e-06)\n",
      "          (k_norm): Qwen3RMSNorm((128,), eps=1e-06)\n",
      "        )\n",
      "        (mlp): Qwen3MLP(\n",
      "          (gate_proj): Linear(in_features=1024, out_features=3072, bias=False)\n",
      "          (up_proj): Linear(in_features=1024, out_features=3072, bias=False)\n",
      "          (down_proj): Linear(in_features=3072, out_features=1024, bias=False)\n",
      "          (act_fn): SiLU()\n",
      "        )\n",
      "        (input_layernorm): Qwen3RMSNorm((1024,), eps=1e-06)\n",
      "        (post_attention_layernorm): Qwen3RMSNorm((1024,), eps=1e-06)\n",
      "      )\n",
      "    )\n",
      "    (norm): Qwen3RMSNorm((1024,), eps=1e-06)\n",
      "    (rotary_emb): Qwen3RotaryEmbedding()\n",
      "  )\n",
      "  (lm_head): Linear(in_features=1024, out_features=151936, bias=False)\n",
      ")\n"
     ]
    }
   ],
   "execution_count": 53
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": "",
   "id": "56eee76f30647d08",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:11:13.042958Z",
     "start_time": "2025-07-17T11:10:39.707830Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "\n",
    "optimizer = torch.optim.Adam(lora_model.parameters(), lr=0.001)\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "lora_model.to(device)\n",
    "\n",
    "EPOCHS = 50\n",
    "\n",
    "for epoch in range(EPOCHS):\n",
    "\n",
    "    for input_ids in data_loader:\n",
    "        input_ids = input_ids.to(device)\n",
    "\n",
    "        outputs = lora_model(\n",
    "            input_ids, labels=input_ids\n",
    "        )\n",
    "\n",
    "        loss = outputs.loss\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        if epoch % 10 == 0:\n",
    "            print(f'Epoch {epoch + 1}, Loss: {loss:.4f}')\n",
    "\n"
   ],
   "id": "9d23efe865e1c102",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1, Loss: 8.3108\n",
      "Epoch 11, Loss: 0.4896\n",
      "Epoch 21, Loss: 0.1294\n",
      "Epoch 31, Loss: 0.1155\n",
      "Epoch 41, Loss: 0.1101\n"
     ]
    }
   ],
   "execution_count": 55
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:13:31.222103Z",
     "start_time": "2025-07-17T11:13:23.258511Z"
    }
   },
   "cell_type": "code",
   "source": [
    "model_name = \"Qwen/Qwen3-0.6B\"\n",
    "base_model = AutoModelForCausalLM.from_pretrained(model_name)\n",
    "\n",
    "prompt = \"你是谁\"\n",
    "messages = [\n",
    "    {\"role\": \"user\", \"content\": prompt}\n",
    "]\n",
    "text = tokenizer.apply_chat_template(\n",
    "    messages,\n",
    "    tokenize=False,\n",
    "    add_generation_prompt=True,\n",
    "    enable_thinking=False\n",
    ")\n",
    "model_inputs = tokenizer([text], return_tensors=\"pt\")\n",
    "generated_ids = lora_model.generate(**model_inputs, max_new_tokens=32768)\n",
    "# generated_ids = base_model.generate(**model_inputs, max_new_tokens=32768)\n",
    "content = tokenizer.decode(generated_ids[0])\n",
    "print(content)"
   ],
   "id": "399b10bb3f9e97c",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading Model from https://www.modelscope.cn to directory: /Users/dadudu/.cache/modelscope/hub/models/Qwen/Qwen3-0.6B\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025-07-17 19:13:24,517 - modelscope - INFO - Target directory already exists, skipping creation.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<|im_start|>user\n",
      "你是谁<|im_end|>\n",
      "<|im_start|>assistant\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "我是大都督周瑜的AI助手\n",
      "<|im_end|>\n"
     ]
    }
   ],
   "execution_count": 59
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:13:50.385606Z",
     "start_time": "2025-07-17T11:13:50.307458Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 保存LoRA学到的参数\n",
    "lora_model.save_pretrained(\"./Zhouyu-Qwen3-0.6B\")"
   ],
   "id": "4cd8e61353edeb5a",
   "outputs": [],
   "execution_count": 60
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:15:34.743406Z",
     "start_time": "2025-07-17T11:15:27.357642Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from peft import PeftModel\n",
    "\n",
    "from modelscope import AutoModelForCausalLM\n",
    "from modelscope import AutoTokenizer\n",
    "\n",
    "model_name = \"Qwen/Qwen3-0.6B\"\n",
    "model = AutoModelForCausalLM.from_pretrained(model_name)\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
    "model = PeftModel.from_pretrained(model, \"./Zhouyu-Qwen3-0.6B\")"
   ],
   "id": "bf43bd09bfc695c7",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading Model from https://www.modelscope.cn to directory: /Users/dadudu/.cache/modelscope/hub/models/Qwen/Qwen3-0.6B\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025-07-17 19:15:28,614 - modelscope - INFO - Target directory already exists, skipping creation.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading Model from https://www.modelscope.cn to directory: /Users/dadudu/.cache/modelscope/hub/models/Qwen/Qwen3-0.6B\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025-07-17 19:15:34,563 - modelscope - INFO - Target directory already exists, skipping creation.\n"
     ]
    }
   ],
   "execution_count": 63
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-17T11:15:38.370447Z",
     "start_time": "2025-07-17T11:15:36.454023Z"
    }
   },
   "cell_type": "code",
   "source": [
    "prompt = \"你是谁\"\n",
    "messages = [\n",
    "    {\"role\": \"user\", \"content\": prompt}\n",
    "]\n",
    "text = tokenizer.apply_chat_template(\n",
    "    messages,\n",
    "    tokenize=False,\n",
    "    add_generation_prompt=True,\n",
    "    enable_thinking=False\n",
    ")\n",
    "model_inputs = tokenizer([text], return_tensors=\"pt\")\n",
    "generated_ids = model.generate(**model_inputs, max_new_tokens=32768)\n",
    "content = tokenizer.decode(generated_ids[0])\n",
    "print(content)"
   ],
   "id": "6e3b016c3c66c0e4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<|im_start|>user\n",
      "你是谁<|im_end|>\n",
      "<|im_start|>assistant\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "我是你的虚拟助手，我不会直接回答问题，我将根据你的问题提供帮助。<|im_end|>\n"
     ]
    }
   ],
   "execution_count": 64
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
